#!/bin/bash
# date: 2025/5/15
# desc: 创建一个自定义准入控制器webhook服务

# 准入控制有 验证 和 变更 两种类型，主要是接收k8s的 AdmissionReview 请求加工处理返回
# 1. 部署webhook为deployment和service
# 2. 配置准入控制类型指向webhook的service。可以限制到pod、Namespace等

# 流程: 生产证书 - webhook服务挂载证书 - 准入控制器绑定ca.crt、webhook服务、指定哪些接口操作会被控制

# 要求:
# 1. 确认kube-apiserver 启动准入插件，默认启用--enable-admission-plugins=MutatingAdmissionWebhook,ValidatingAdmissionWebhook
# 2. 确认启动 admissionregistration.k8s.io/v1 API
# kubectl api-resources |grep admissionregistration.k8s.io/v1
# 3. 编写 webhook 处理API发送的 AdmissionReview 请求，返回相同版本对象

gen_cert() {
    openssl genrsa -out ca.key 2048
    openssl req -new -x509 -days 3650 -key ca.key -subj "/CN=webhook-ca" -out ca.crt

    openssl genrsa -out server.key 2048
    cat >openssl.cnf <<EOF
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name

[req_distinguished_name]
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = adminssionwebhook.default.svc
EOF

    openssl req -new -key server.key -subj "/CN=adminssionwebhook.default.svc" \
        -config openssl.cnf -out server.csr
    openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial \
        -extensions v3_req -extfile openssl.cnf -out server.crt

    # check cert
    openssl x509 -in server.crt -text -noout | grep -A1 "Subject Alternative Name"

    mkdir ssl
    mv ca* server* openssl.cnf ssl
    cp ssl/server.key ssl/tls.key
    cp ssl/server.crt ssl/tls.crt
}

docker_image() {
    docker build -t hub.abc.com/basic/admissionwebhook .
    docker push hub.abc.com/basic/admissionwebhook
}

kubectl_object() {
    kubectl create secret tls webhook-tls \
        --cert=ssl/server.crt \
        --key=ssl/server.key \
        --namespace=default

    sleep 1
    kubectl apply -f adminssionwebhook.yaml
    # cat ca.crt | base64 | tr -d '\n'
    kubectl apply -f adminssionwebhook-mutate.yaml

    sleep 3
    kubectl create ns test-webhook
    kubectl label ns test-webhook webhook-enabled=true

    sleep 3
    kubectl apply -f alpine.yaml
    kubectl get events -n test-webhook --field-selector type=Warning
    #kubectl -n test-webhook get pod alpine-795454567d-jcxjw -o yaml | grep ops
    # opswebhook:test
}

delete() {
    kubectl delete -f alpine.yaml
    kubectl delete ns test-webhook
    kubectl delete -f adminssionwebhook-mutate.yaml
    kubectl delete -f adminssionwebhook.yaml
    kubectl delete secret webhook-tls
}

main() {
    docker_image
    gen_cert
    kubectl_object
}

main
